#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
#include <QNetworkDatagram>
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //创建QListWidget来显示服务端接收到的消息
    list_widget=new QListWidget(this);
    list_widget->setGeometry(50,50,600,500);

    //创建出udpsocket对象,并将其挂到对象树上
    socket=new QUdpSocket(this);
    //设置窗口标题
    this->setWindowTitle("服务器");

    //连接信号槽
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processRequest);

    //这里一定是先连接信号槽，再绑定端口号，因为绑定端口号成功之后，就意味着请求就可以被收到了
    //如果先绑定端口号，再连接信号槽，那么他们之间的这段时间如果有请求到了，服务端就无法提供请求了

    //绑定端口号
    bool ret=socket->bind(QHostAddress::Any,9090);//一个端口号只能绑定一个服务
    //Any:表示本主机所有网络ip
    if(ret==false)
    {
        //绑定失败,弹出一个提示对话框
        QMessageBox::critical(this,"服务器出错",socket->errorString());
        //socket->errorString()是对errno错误详细情况的封装,相当于perror
        return;
    }
}

Widget::~Widget()
{
    delete ui;
}

void Widget::processRequest()
{
    //1、读取请求中的数据包
    const QNetworkDatagram requestDatagram=socket->receiveDatagram();
    //获取数据包中的有效信息-有效载荷
    QString request=requestDatagram.data();
    //requestDatagram.data();返回一个QByteArray字节数组，QByteArray可以赋值给QString对象
    //2、根据请求计算响应(回显服务器，response就是request)
    const QString response=process(request);
    //3、将响应写回到客户端
    //构造UDP数据包
    QNetworkDatagram responseDatagram(response.toUtf8(),//取出QString内部的QByteArray字节数组
                                      requestDatagram.senderAddress(),//对端的ip
                                      requestDatagram.senderPort());//对端port
    //发送给客户端
    socket->writeDatagram(responseDatagram);
    //4、将本次交互的信息写到纵向列表界面上
    QString log="["+requestDatagram.senderAddress().toString()+":"+QString::number(requestDatagram.senderPort())
            +"] request:"+request+", response:"+response;
    list_widget->addItem(log);
}

//业务处理函数
QString Widget::process(const QString &request)
{
    //回显服务器，请求和响应完全一致
    return request;
}

